﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WinScriptEngine.Parses.Interface;

namespace WinScriptEngine.Parses.Scope
{

    #region ==== 异常类 ====
    [Serializable]
    public class SymbolException : RuntimeException
    {
        public SymbolException() { }
        public SymbolException(string message) : base(message) { }
        public SymbolException(string message, Exception inner) : base(message, inner) { }
        protected SymbolException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
    }
    #endregion

    /// <summary>
    /// 函数委托类型
    /// </summary>
    /// <param name="invoke">当前执行环境</param>
    /// <param name="params">参数列表</param>
    /// <returns>函数运算结果</returns>
    delegate Metadata FunctionVariable(InvokeEnvironment invoke, List<Metadata> @params);

    /// <summary>
    /// 符号类，可读取、设置、执行。
    /// </summary>
    class Symbols
    {
        /// <summary>
        /// 符号
        /// </summary>
        Dictionary<string, Metadata> symbols = new();

        /// <summary>
        /// 设置符号值
        /// </summary>
        /// <param name="name">符号名称</param>
        /// <param name="value">值</param>
        public void Set(string name, Metadata value)
            => symbols[name] = value;

        /// <summary>
        /// 获得符号的值
        /// </summary>
        /// <param name="name">符号名称</param>
        /// <returns>符号的值</returns>
        public Metadata Get(string name)
        {
            Metadata value;
            if (!symbols.TryGetValue(name, out value))
                throw new SymbolException("符号未定义!");
            return value;
        }

        /// <summary>
        /// 执行符号
        /// </summary>
        /// <param name="invoke">执行环境</param>
        /// <param name="name">符号名称</param>
        /// <param name="params">参数列表</param>
        /// <returns>执行的结果</returns>
        public Metadata Invoke(InvokeEnvironment invoke, string name, List<Metadata> @params)
        {
            Metadata function = Get(name);
            if (function.type != MetadataType.Func)
                throw new SymbolException("符号不可执行!");

            FunctionVariable functionVariable = function.@object as FunctionVariable;
            if (functionVariable == null)
                throw new SymbolException("符号不可执行!");

            return functionVariable(invoke, @params);
        }
    }
}
